<template>
  <div :class="['table-container', { 'fix-row-button': isfixedRowButton }]">
    <div class="title">{{ title }}</div>
    <table class="table" border="0" cellspacing="0">
      <thead>
        <tr>
          <th v-for="i in totalCol" :width="100 / totalCol + '%'"></th>
          <th v-if="!readonly && !disabled"></th>
        </tr>
      </thead>
      <tbody>
        <tr
          v-for="(row, rowIndex) in rowData"
          :key="row.id"
          :class="['table-row', { 'fix-button': isfixedRowButton }]"
        >
          <template v-for="(cell, cellIndex) in row.cells">
            <td
              :key="cell.id"
              :colspan="cell.colspan"
              :rowspan="cell.rowspan"
              :class="[
                'table-cell',
                cell.controllerType,
                {
                  disabled:
                    (disabled || cell.disabled) &&
                    cell.controllerType !== 'LABEL',
                },
              ]"
              @click="handleFocus(cell.id + '_inputComponent')"
            >
              <i v-if="cell.required == true && cell.controllerType != 'LABEL'" class="required-icon">*</i>
              <!-- Label -->
              <span
                v-if="cell.controllerType == 'LABEL'"
                class="label"
                :style="{
                  width: cell.width,
                  'min-width': cell.width ? 'auto' : '80px',
                }"
                >{{ cell.content }}</span
              >
              <!-- 组件 -->
              <span
                v-else-if="
                  !disabled &&
                  [
                    'INPUT',
                    'DATETIME',
                    'DATE',
                    'RADIO',
                    'SELECT',
                    'MULTIPLESELECT',
                    'NUMBER',
                    'CHECKBOX',
                    'UPLOAD',
                    'DATETIMERANGE'
                  ].includes(cell.controllerType)
                "
                class="input"
                :style="{ 'min-width': cell.width ? 'auto' : '80px' }"
              >
                <component
                  :is="componentMap[cell.controllerType]"
                  :ref="cell.id + '_inputComponent'"
                  v-model="formObj[cell.content]"
                  :options="cell.options"
                  :disabled="readonly || cell.disabled"
                  :accept="cell.accept"
                  @change="handleCellChange(cell, $event)"
                  @file-click="handleFileClick($event, cell)"
                ></component>
              </span>
              <!-- 其他 -->
              <span v-else>
                <TUpload
                  v-if="['UPLOAD'].includes(cell.controllerType)"
                  :ref="cell.id + '_inputComponent'"
                  v-model="formObj[cell.content]"
                  :disabled="readonly || disabled || cell.disabled"
                  :accept="cell.accept"
                  @file-click="handleFileClick($event, cell)"
                ></TUpload>
                <TInput
                  v-else
                  :ref="cell.id + '_inputComponent'"
                  v-model="formObj[cell.content]"
                  :disabled="readonly || disabled || cell.disabled"
                ></TInput>
              </span>
              <div v-if="!!warningValue[cell.id]" class="warning-tip">
                <slot name="warningTip">
                  <span>数据异常</span>
                </slot>
              </div>
            </td>
          </template>
          <td
            class="row-operate"
            v-if="
              !readonly &&
              !disabled &&
              (isShowRowAddBtn(row) || isShowRowDelBtn(row))
            "
          >
            <div class="row-after">
              <!-- 添加下一行 -->
              <i
                v-if="isShowRowAddBtn(row)"
                class="add-btn el-icon-circle-plus-outline"
                @click="handleAddRowClick(row)"
              ></i>
              <!-- 删除下一行 -->
              <i
                v-if="isShowRowDelBtn(row)"
                class="delete-btn el-icon-remove-outline"
                @click="handleDelRowClick(row)"
              ></i>
            </div>
          </td>
        </tr>
      </tbody>
    </table>
    <div class="add-last-row">
      <!-- 添加行 -->
      <el-button
        v-if="showAddLastRow && rowData.length && !disabled"
        type="text"
        @click="handleAddRowClick(rowData[rowData.length - 1])"
        >添加行</el-button
      >
    </div>
  </div>
</template>
<script>
import TDateTimePicker from "./components/TDateTimePicker.vue";
import TDatePicker from "./components/TDatePicker.vue";
import TInput from "./components/TInput.vue";
import TSelect from "./components/TSelect.vue";
import TRadio from "./components/TRadio.vue";
import TMultipleSelect from "./components/TMultipleSelect.vue";
import TNumber from "./components/TNumber.vue";
import TCheckBox from "./components/TCheckBox.vue";
import TUpload from "./components/TUpload.vue";
import TDateTimeRangePicker from "./components/TDateTimeRangePicker.vue";
export default {
  components: {
    TDateTimePicker,
    TDatePicker,
    TInput,
    TSelect,
    TRadio,
    TMultipleSelect,
    TNumber,
    TCheckBox,
    TUpload,
    TDateTimeRangePicker
  },
  props: {
    // 模板配置
    templateConfig: {
      type: Object,
      default: null,
    },
    // 后端的表单字段配置
    formConfig: {
      type: Object,
      default: null,
    },
    // 表单数据
    formData: {
      type: Object,
      default: null,
    },
    // 不可编辑，不显示单元格组件
    disabled: {
      type: Boolean,
      default: false,
    },
    // 只读(不可编辑)，显示单元格组件，优先级高于disabled
    readonly: {
      type: Boolean,
      default: false,
    },
    // 是否显示添加行
    showAddLastRow: {
      type: Boolean,
      default: false,
    },
    // 是否固定行按钮
    isfixedRowButton: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      title: "",
      totalCol: 0,
      rowData: [],
      // 提交表单数据
      formObj: {},
      componentMap: {
        RADIO: "TRadio",
        SELECT: "TSelect",
        INPUT: "TInput",
        DATETIME: "TDateTimePicker",
        DATE: "TDatePicker",
        MULTIPLESELECT: "TMultipleSelect",
        NUMBER: "TNumber",
        CHECKBOX: "TCheckBox",
        UPLOAD: "TUpload",
        DATETIMERANGE: "TDateTimeRangePicker"
      },
      warningValue: {},
    };
  },
  watch: {
    templateConfig: {
      handler(newValue) {
        const _newValue = this.deepCopyData(newValue);
        if (_newValue) {
          this.title = _newValue.title || "";
          this.totalCol = _newValue.totalCol || 0;
          this.rowData = _newValue.config || [];

          this.initTable();
        }
      },
      deep: true,
      immediate: true,
    },
  },
  methods: {
    // 初始化
    initTable() {
      this.initColspan();
      this.initFormData();
      this.$nextTick(() => {
        this.initWarningValidation();
        this.$emit(
          "inited",
          this.rowData,
          JSON.parse(JSON.stringify(this.formData))
        );
      });
    },
    // 初始化提交的表单
    initFormData() {
      const _formObj = {};
      const rowData = this.rowData;
      for (let i = 0; i < rowData.length; i++) {
        const cells = rowData[i].cells;
        for (let j = 0; j < cells.length; j++) {
          const cell = cells[j];
          if (
            [
              "INPUT",
              "DATETIME",
              "DATE",
              "RADIO",
              "SELECT",
              "MULTIPLESELECT",
              "NUMBER",
              "CHECKBOX",
              "UPLOAD",
              "DATETIMERANGE"
            ].includes(cell.controllerType)
          ) {
            const _val = this.initFormValue(cell.content);
            // 默认值
            let _defaultValue = this.getDefaultValueByCell(cell);
            _formObj[cell.content] = _val == null ? _defaultValue : _val;
          }
        }
      }
      this.formObj = _formObj;
    },
    getDefaultValueByCell(cell) {
      let _defaultValue = cell.defaultValue;
      if (_defaultValue === "currentDateTime") {
        // 当前时间
        if (cell.controllerType === "DATETIME") {
          _defaultValue = this.parseTime(new Date(), "{y}-{m}-{d} {h}:{i}:{s}");
        } else if (cell.controllerType === "DATE") {
          _defaultValue = this.parseTime(new Date(), "{y}-{m}-{d}");
        }
      }
      return _defaultValue;
    },
    initFormValue(content) {
      if (!content) {
        return null;
      }

      if (this.formObj[content]) {
        return this.formObj[content];
      }

      const keys = content.match(/(?<=\$\{)[a-zA-Z0-9_\.\[\]]+(?=\})/);
      if (!keys?.length) {
        return null;
      }

      let value = null;
      try {
        value = eval(`this.formData.${keys[0]}`);
      } catch (error) {
        value = null;
      }
      return value;
    },
    // 初始化表格配置(模板插值，跨列对齐，行复制)
    initColspan() {
      let { rowData, totalCol } = this;
      for (let i = 0; i < rowData.length; i++) {
        const row = rowData[i];
        const cells = row.cells;

        // 按比例分配colspan
        const total = cells.reduce(
          (p, n) => {
            return { colspan: p.colspan + n.colspan };
          },
          { colspan: 0 }
        ).colspan;

        let lastSpan = totalCol;
        for (let j = 0; j < cells.length; j++) {
          const cell = cells[j];

          cell.colspan = Math.floor((cell.colspan / total) * totalCol);

          lastSpan -= cell.colspan;

          // 根据后端返回的相关字段的配置，调整前端模板配置
          this.getFormConfigItem(cell);
        }

        // 剩余分配colspan
        if (lastSpan > 0) {
          const _sortCell = [...cells].reverse().sort((a, b) => {
            return a.colspan > b.colspan ? -1 : 1;
          });
          const _sortCellId = _sortCell.map((ele) => ele.id);
          for (let z = 0; z < lastSpan; z++) {
            const _s = row.cells.find((ele) => ele.id == _sortCellId[z]);
            if (_s) {
              _s.colspan += 1;
            }
          }
        }

        // rowspan为0，则为被覆盖的，过滤掉
        row.cells = cells.filter((ele) => ele.rowspan != 0);
      }

      // 初始化完成后，对含有属性copyValuesRows行进行复制
      const newRows = [];
      let copyIndex = rowData.findIndex(
        (ele) => !!ele.copyValuesRows && typeof ele.copyValuesRows == "number"
      );
      let copyRow = rowData[copyIndex];
      if (copyRow) {
        let copyNum = copyRow.copyValuesRows;

        if (copyRow.cells && copyRow.cells[0]) {
          const keys = copyRow.cells[0].content.match(
            /(?<=\$\{)[a-zA-Z0-9_\[\]\.]+(?=\[\d+\](\.[a-zA-Z0-9_]+)+\})/g
          );
          if (keys?.length) {
            let list = [];
            try {
              list = eval(`this.formData.${keys[0]}`);
            } catch (error) {
              list = [];
            }
            if (copyNum < list.length - 1) {
              copyNum = list.length - 1;
            }
          }
        }

        for (let k = 0; k < copyNum; k++) {
          let newRow = this.doCopyRow(copyRow, () => {
            return new Date().getTime() + k;
          });
          newRows.push(newRow);

          copyRow = newRows[k];
        }
        this.rowData.splice(copyIndex + 1, 0, ...newRows);
      }
    },
    getFormConfigItem(cellItem) {
      for (let key in cellItem) {
        let val = cellItem[key];
        // 需要插入值
        if (/^\$\.[a-zA-Z0-9_\.\|]+/.test(val)) {
          if (!this.formConfig) {
            continue;
          }
          const configField = val.match(/(?<=\$)[a-zA-Z0-9_\.]+/g);
          if (!configField?.length) {
            continue;
          }
          try {
            const configVals = configField.map((cf) => {
              return new Function(`return this.formConfig${cf}`).call(this);
            });
            // const configVal = new Function(
            //   `return this.formConfig${configField[0]}`
            // ).call(this);
            if (key == "options") {
              cellItem[key] = this.getOptionsValue(configVals[0]);
            } else {
              cellItem[key] = configVals.join(" \\ ");
            }
          } catch (err) {
            console.error(err);
          }
        } else if (key == "options") {
          cellItem[key] = this.getOptionsValue(cellItem[key]);
        }
      }
    },
    // 初始化warning校验
    initWarningValidation() {
      this.rowData.forEach((row) => {
        if (row.cells?.length) {
          row.cells.forEach((cell) => {
            // 单元格校验
            this.handleCellWarningValidation(cell);
          });
        }
      });
    },
    // 转换模板中的options
    getOptionsValue(arr) {
      const type = Object.prototype.toString.call(arr);
      if (type == "[object Array]") {
        let res = [];
        arr.forEach((ele) => {
          if (Object.prototype.toString.call(ele) == "[object String]") {
            res.push({ value: ele, label: ele });
          } else {
            res.push(ele);
          }
        });
        return res;
      } else if (type == "[object String]") {
        return this.getOptionsValue(JSON.parse(arr));
      } else {
        return [];
      }
    },
    // 每行的添加按钮的显示隐藏
    isShowRowAddBtn(row) {
      const type = Object.prototype.toString.call(row.showAddBtn);
      if (type == "[object Function]") {
        return row.showAddBtn(row);
      }
      if (type == "[object Boolean]") {
        return row.showAddBtn;
      }
      return false;
    },
    // 每行的删除按钮的显示隐藏
    isShowRowDelBtn(row) {
      const type = Object.prototype.toString.call(row.showDelBtn);
      if (type == "[object Function]") {
        return row.showDelBtn(row, this.rowData);
      }
      if (type == "[object Boolean]") {
        return row.showDelBtn;
      }
      return false;
    },
    // 插入行
    handleAddRowClick(row) {
      let oriRow = this.rowData.find((ele) => ele.id == row.id);
      if (!oriRow) {
        return;
      }

      const newRow = this.doCopyRow(oriRow);

      const rowIndex = this.rowData.findIndex((ele) => ele.id == row.id);
      this.rowData.splice(rowIndex + 1, 0, newRow);

      if (rowIndex + 1 == this.rowData.length - 1) {
        // 插入最后一行
        for (let index = 0; index < newRow.cells.length; index++) {
          const cellele = newRow.cells[index];
          this.$set(
            this.formObj,
            cellele.content,
            this.getDefaultValueByCell(cellele)
          );
        }
      } else {
        // 中间插入的行的后排行，数组下标都+1
        const exp = new RegExp("(?<=\\[)\\d+(?=\\](\\.\\w+)+\\})", "g");
        for (
          let index = this.rowData.length - 1;
          index > rowIndex + 1;
          index--
        ) {
          const rowele = this.rowData[index];
          if (!rowele.cells?.length) {
            continue;
          }
          for (let j = 0; j < rowele.cells.length; j++) {
            const cellele = rowele.cells[j];
            const itemIndex = cellele.content.match(exp);
            if (itemIndex?.length) {
              const oldKey = cellele.content;
              // 数组下标都+1
              const _index = Number(itemIndex[0]);
              cellele.content = cellele.content.replace(exp, _index + 1);
              // 组件绑定值
              this.$set(
                this.formObj,
                cellele.content,
                this.formObj[oldKey] || ""
              );
              this.$set(
                this.formObj,
                oldKey,
                this.getDefaultValueByCell(cellele)
              );
            }
          }
        }
      }

      this.$nextTick(() => {
        this.initWarningValidation();
      });
      this.$emit("add-row", this.rowData[rowIndex + 1]);
    },
    // 复制行
    doCopyRow(oriRow, rowNumCallback) {
      let newRow = this.deepCopyData(oriRow);
      const rowNum = rowNumCallback ? rowNumCallback() : new Date().getTime();
      newRow.id = `row_${rowNum}`;
      newRow.cells.forEach((cell, i) => {
        cell.id = `cell_${rowNum}_${i + 0}`;
        // 增加列
        // cell.content = cell.content.replace(
        //   /(?<=\$\{[a-zA-Z0-9_\[\]\.]+)\w+(?=\})/g,
        //   "others"
        // );
        // 增加行
        const exp = new RegExp("(?<=\\[)\\d+(?=\\](\\.\\w+)+\\})", "g");
        const index = cell.content.match(exp);
        if (index?.length) {
          const _index = Number(index[0]);
          cell.content = cell.content.replace(exp, _index + 1);
        }

        // 跨行
        if (cell.rowspan != 1) {
          let startFlag = false;
          for (let k = this.rowData.length - 1; k >= 0; k--) {
            const c = this.rowData[k];
            if (c.id == row.id) {
              startFlag = true;
            }
            if (!startFlag) {
              continue;
            }
            if (c.cells[i].rowspan == 0) {
              continue;
            }
            c.cells[i].rowspan++;
            break;
          }
          cell.rowspan = 0;
        }
      });
      return newRow;
    },
    // 删除行
    handleDelRowClick(row) {
      const rowIndex = this.rowData.findIndex((ele) => ele.id == row.id);
      if (rowIndex == -1) {
        return;
      }
      // 删除表格行
      const deleteRow = this.rowData.splice(rowIndex, 1);
      const _formObj = { ...this.formObj };
      if (this.rowData.length == rowIndex) {
        // 删掉最后一行
        for (let index = 0; index < deleteRow[0].cells.length; index++) {
          const cellele = deleteRow[0].cells[index];
          delete _formObj[cellele.content];
        }
        this.formObj = _formObj;
      } else {
        // 删掉中间行
        // 删除的行的后排行，数组下标都-1
        const exp = new RegExp("(?<=\\[)\\d+(?=\\](\\.\\w+)+\\})", "g");
        for (let index = rowIndex; index <= this.rowData.length - 1; index++) {
          const rowele = this.rowData[index];
          if (!rowele.cells?.length) {
            continue;
          }
          for (let j = 0; j < rowele.cells.length; j++) {
            const cellele = rowele.cells[j];
            const itemIndex = cellele.content.match(exp);
            if (itemIndex?.length) {
              const oldKey = cellele.content;
              // 数组下标都-1
              const _index = Number(itemIndex[0]);
              cellele.content = cellele.content.replace(exp, _index - 1);
              // 组件绑定值
              _formObj[cellele.content] = this.formObj[oldKey] || "";
              delete _formObj[oldKey];
            }
          }
        }
        this.formObj = _formObj;
      }
    },
    // 获取表单数据
    getSubmitFormData() {
      const params = this.getFormatFormData();
      return params;
    },
    // 提交时的校验（获取填写表单时的校验）
    validate() {
      let validCell = {
        flag: true,
        cell: null,
      };
      const config = this.rowData;
      const _formObj = this.formObj;
      for (let i = 0; i < config.length; i++) {
        const row = config[i];
        for (let j = 0; j < row.cells.length; j++) {
          const col = row.cells[j];
          // col.pattern && !col.pattern.test(_formObj[content])
          validCell = {
            flag: true,
            cell: { ...col },
          };
          if (col.required == true && col.controllerType != "LABEL") {
            const type = Object.prototype.toString.call(_formObj[col.content]);
            if (
              [
                "[object Object]",
                "[object Null]",
                "[object Undefined]",
              ].includes(type) &&
              !_formObj[col.content]
            ) {
              validCell.flag = false;
              break;
            } else if (
              type == "[object Array]" &&
              !_formObj[col.content].length
            ) {
              validCell.flag = false;
              break;
            } else if (
              type == "[object String]" &&
              !_formObj[col.content]?.trim()
            ) {
              validCell.flag = false;
              break;
            } else if (
              type == "[object Number]" &&
              !_formObj[col.content] &&
              _formObj[col.content] != 0
            ) {
              validCell.flag = false;
              break;
            }
          }
        }
        if (!validCell.flag) {
          break;
        }
      }
      if (
        !validCell.cell ||
        !this.$refs[validCell.cell.id + "_inputComponent"]?.length
      ) {
        return validCell;
      }
      // 标识出错误的单元格组件
      if (validCell.flag) {
        this.setCellError(validCell.cell.id, false);
      } else {
        this.setCellError(validCell.cell.id, true);
      }

      return validCell;
    },
    // 获取填写表单
    getFormatFormData() {
      // let result = this.formData ? this.deepCopyData(this.formData) : {};
      let result = {};
      const _formObj = { ...this.formObj };
      for (let key in _formObj) {
        if (!/^\$\{.+\}$/.test(key)) {
          result[key] = _formObj[key];
          continue;
        }
        const realKeyStrs = key.match(/(?<=\$\{)[^\$]+(?=\})/g);
        realKeyStrs.forEach((realKeyStr) => {
          const allKeys = realKeyStr.match(/[a-zA-Z0-9_]+/g);

          let allKeysStr = "result";
          allKeys.reduce((prev, next) => {
            if (!prev) {
              return next;
            }
            if (/^\d+$/.test(prev)) {
              allKeysStr += `[${prev}]`;
            } else {
              allKeysStr += `.${prev}`;
            }

            if (/^\d+$/.test(next)) {
              if (!eval(`${allKeysStr}`)?.length) {
                eval(`${allKeysStr} = []`);
              }
            } else {
              if (!eval(`${allKeysStr}`)) {
                eval(`${allKeysStr} = { ${next}: null}`);
              } else if (!eval(`${allKeysStr}.${next}`)) {
                eval(`${allKeysStr}.${next} = null`);
              }
            }
            return next;
          }, "");
          eval(`result.${realKeyStr} = _formObj[key] || ""`);
        });
      }
      return result;
    },
    handleFocus(refId) {
      const ref = this.$refs[refId];
      if (ref?.length == 1) {
        ref[0].focus();
      }
    },
    handleCellChange(cell, value) {
      // 有必填校验的单元格字段，值变化去除校验（在报错时做校验）
      if (cell.required == true) {
        const com = this.$refs[cell.id + "_inputComponent"];
        if (com?.length) {
          this.setCellError(cell.id, false);
        }
      }
      // 单元格change回调
      if (
        cell?.change &&
        Object.prototype.toString.call(cell.change) == "[object Function]"
      ) {
        cell.change(value, this.formObj);
      }
      // 单元格校验
      this.handleCellWarningValidation(cell);

      this.$emit("change", cell, value, this.formObj);
    },
    // 单元格warning校验
    handleCellWarningValidation(cell) {
      if (
        cell.warningVerification &&
        cell.warningVerification.trigger == "change"
      ) {
        const ruleType = Object.prototype.toString.call(
          cell.warningVerification.rule
        );
        if (ruleType == "[object Function]") {
          const ruleFlag = cell.warningVerification.rule(cell, {
            ...this.formObj,
          });
          this.$set(this.warningValue, cell.id, !ruleFlag);
          this.setCellError(cell.id, !ruleFlag, "validate-warning");
        }
      }
    },
    handleFileClick(file, cell) {
      this.$emit("file-click", file, cell);
    },
    updateFormObj(key, value) {
      this.formObj[key] = value;
    },
    clearForm() {
      this.formObj = {};
    },
    // 设置单元格的异常
    setCellError(cellId, flag = false, errType = "validate-error") {
      if (!cellId) {
        return;
      }
      if (this.$refs[cellId + "_inputComponent"]?.length) {
        if (flag) {
          // 添加异常
          this.$refs[cellId + "_inputComponent"][0].$el.classList.add(errType);
        } else {
          // 移除异常
          this.$refs[cellId + "_inputComponent"][0].$el.classList.remove(
            errType
          );
        }
      }
    },
  },
};
</script>
<style lang="scss" scoped>
.table-container {
  height: 100%;
  width: 100%;
  padding-bottom: 42px;
  overflow-x: auto;
  .title {
    text-align: center;
    margin-bottom: 20px;
    font-size: 16px;
    color: #303133;
  }
  .table {
    width: 100%;
    background: #ffffff;
    font-size: 15px;
    .table-row {
      position: relative;
      &:first-child {
        td:not(.row-operate) {
          border-top: 1px solid #dcdcdc;
        }
      }
      & > td:first-child {
        border-left: 1px solid #dcdcdc;
      }
      &:not(.fix-button) {
        .row-after {
          width: 40px;
          text-align: center;
          font-size: 20px;
          color: #909399;
          cursor: pointer;
          i {
            display: none;
            &:hover {
              color: #409eff;
            }
          }
        }
        &:hover {
          .row-after {
            i {
              display: inline;
            }
          }
        }
      }
      &.fix-button {
        .row-after {
          width: 60px;
          font-size: 26px;
          color: #409eff;
          cursor: pointer;
          .add-btn {
            margin-right: 6px;
          }
        }
      }
    }
    ::v-deep .table-cell {
      border-bottom: 1px solid #dcdcdc;
      border-right: 1px solid #dcdcdc;
      padding: 8px 15px;
      position: relative;
      .required-icon {
        color: red;
        position: absolute;
        left: 0px;
        top: 50%;
        transform: translateY(-30%);
        font-size: 19px;
      }
      &.LABEL {
        text-align: center;
      }
      .el-textarea.is-disabled .el-textarea__inner,
      .el-input.is-disabled .el-input__inner {
        background-color: #ffffff;
      }
      .label {
        display: inline-block;
        font-weight: 600;
        font-size: 14px;
        color: #666666;
      }
      .input {
        display: inline-block;
        width: 100%;
      }
      .el-select {
        width: 100%;
      }
      .el-input__inner {
        border: none;
        padding: 0;
        border-radius: 0;
        color: #313131;
      }
      .el-textarea__inner {
        line-height: 20px;
        border: 0;
        border-radius: 0;
        padding: 0;
        overflow: hidden;
        text-align: center;
        word-break: break-word;
        color: #313131;
      }
      .input-text {
        font-size: 14px;
        text-align: center;
      }
      .validate-error {
        border: 1px solid #ff9393;
        border-radius: 3px;
      }
      .validate-warning {
        .el-textarea__inner,
        .el-radio.is-checked .el-radio__label,
        .el-checkbox.is-checked .el-checkbox__label {
          color: #f56c6c;
        }
        .el-radio__input.is-checked .el-radio__inner,
        .el-checkbox__input.is-checked .el-checkbox__inner {
          border-color: #f56c6c;
          background: #f56c6c;
        }
      }
      &:hover {
        .warning-tip {
          display: block;
        }
      }
      .warning-tip {
        display: none;
        position: absolute;
        left: 50%;
        top: 100%;
        transform: translate(-50%, 5px);
        z-index: 100;
        background: #303133;
        padding: 7px 10px;
        border-radius: 3px;
        font-size: 14px;
        color: #ffffff;
        animation: fade 0.6s;
        &::before {
          content: "";
          position: absolute;
          left: 50%;
          bottom: 100%;
          transform: translateX(-50%);
          width: 0;
          height: 0;
          border-top: 5px solid transparent;
          border-right: 5px solid transparent;
          border-left: 5px solid transparent;
          border-bottom: 5px solid #303133;
        }
      }
    }
  }
  .add-last-row {
    // position: absolute;
    // right: 0;
    // top: 100%;
    text-align: right;
  }
}
@keyframes fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
</style>
<style lang="scss">
.form-template-popover-tip {
  min-width: auto;
  padding: 10px 12px;
}
</style>
